package nnet2.net;

import java.util.ArrayList;
import java.util.LinkedList;

public class InputLayer {

    // Zmienne warstwy
    private double bias;         // obciazenie
    private ArrayList<Double> x;          // wektor wejsciowy
    private LinkedList<Double> inDelay;    // opoznienie wejscia
    private LinkedList<Double> outDelay;   // opoznienie wyjscia

    // Zmienne pomocnicze
    private int inDelaySize;
    private int outDelaySize;
    private int inputSize;

    public InputLayer(int inputSize, int inDalaySize, int outDelaySize, boolean bias){
        if (bias)
            this.bias = 1;
        else
            this.bias = 0;

        initInput(inputSize);
        initInputDelay(inDalaySize);
        initOutputDelay(outDelaySize);
    }

    private void initInput(int inputSize) {
    	this.inputSize = inputSize;
        this.x = new ArrayList<Double>(inputSize);
    }

    private void initInputDelay(int size){
        this.inDelaySize = size;
        this.inDelay = new LinkedList<Double>();
        for(int i = 0; i < size; i++)
            this.inDelay.add(0.0);
    }

    private void initOutputDelay(int size){
        this.outDelaySize = size;
        this.outDelay = new LinkedList<Double>();
        for(int i = 0; i < size; i++)
            this.outDelay.add(0.0);
    }

    public double get(int i){
        if( i == 0) return this.bias;
        i -= 1;
        if(i < this.x.size()) return this.x.get(i);
        i -= this.x.size();
        if(i < this.inDelaySize) return this.inDelay.get(i);
        i -= this.inDelaySize;
        
        return this.outDelay.get(i);
    }

    public void pushInput(double f){
        this.inDelay.remove();
        this.inDelay.add(f);
    }

    public void pushOutput(double f){
        this.outDelay.remove();
        this.outDelay.add(f);
    }
    
    public void process(double[] input){
    	if(input.length != this.inputSize){
    		throw new IndexOutOfBoundsException();
    	}
    	this.x.clear();
    	for(int i = 0; i < input.length; i++)
    		this.x.add(i, input[i]);
    }
    
    public int getSize(){
    	return 1 + this.inputSize + this.inDelaySize + this.outDelaySize;
    }
    
    public static void main(String[] args) {
		InputLayer il = new InputLayer(1, 2, 2, false);
		
		double[] f = new double[]{1.0f};
		il.process(f);
		
		il.pushInput(1.5f);
		il.pushInput(2);
		il.pushInput(3);
		il.pushInput(4);
		il.pushInput(5);
		il.pushInput(5.1f);

		il.pushOutput(10f);
		il.pushOutput(9);
		il.pushOutput(8);
		il.pushOutput(7);
		il.pushOutput(6);
		il.pushOutput(5.9f);
		
		for(int i = 0; i< il.getSize(); i++)
			System.out.println(il.get(i));
		
		System.out.format("Size: %d\n", il.getSize());
	}
}

